package com.studerb.service.interfaces;

import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;

import com.studerb.exceptions.ServiceException;
import com.studerb.model.Header;
import com.studerb.model.HeaderThread;
import com.studerb.model.NewsGroup;
import com.studerb.model.Post;
import com.studerb.tasks.interfaces.ITaskListener;

public interface IHeaderService extends IService {

	// void createHeaderThreads(List<Header> headers, NewsGroup newsGroup);

	/**
	 * Deletes all the headers from a specific newsgroup from persistence
	 * Probaly called when a NewsGroup is unsubscribed along with explicit calls
	 * by tasks
	 * <p>
	 * Fires {@link com.studerb.events.NewsGroupEvent NewsGroupEvent} of type
	 * {@link com.studerb.events.NewsGroupEvent.EventType.HEADERS HEADERS} to
	 * indicate that the many headers of a specific NewsGroups have been
	 * modified at once.
	 * <p>
	 * 
	 * @param Newsgroup
	 *            whose headers will be deleted from persistence
	 */
	int deleteAllPosts(NewsGroup newsGroup);

	/**
	 * Creates and submits a task to download all of a newsgroup's headers
	 * <p>
	 * Fires a {@link com.studerb.events.NewsGroupEvent NewsGroupEvent} of type
	 * {@link com.studerb.events.NewsGroupEvent.EventType.HEADERS HEADERS}
	 * indicating that that multiple headers have been updated/created/deleted
	 * 
	 * @param newsGroup
	 * @param taskListeners
	 * @throws ServiceException
	 *             if task is successfully not started
	 * @see com.studerb.tasks.headers.XoverAllCommandTask
	 * @see com.studerb.service.interfaces.ITaskService
	 * @see com.studerb.tasks.interfaces.ITaskListener
	 */
	void downloadAllHeaders(NewsGroup group, ITaskListener... taskListeners) throws ServiceException;

	/**
	 * Creates and submits a task to download a post's article header and body
	 * After completion of the task the headers {@code articleDownloaded boolean
	 * value} should be set to true.
	 * <p>
	 * Fires a {@link com.studerb.events.HeaderEvent HeaderEvent} of type
	 * {@link com.studerb.events.HeaderEvent.EventType.ARTICLE_DOWNLOADED
	 * ARTICLE_DOWNLOADED}
	 * 
	 * @param newsGroup
	 * @param taskListeners
	 * @throws ServiceException
	 *             on errors relating to task submission
	 * @see com.studerb.service.interfaces.ITaskService
	 * @see com.studerb.tasks.interfaces.ITaskListener
	 */
	void downloadArticle(Post post, ITaskListener... taskListeners) throws ServiceException;

	/**
	 * Creates and submits a task to download a post's article body. After
	 * completion of the task the headers {@code articleDownloaded boolean
	 * value} should be set to true.
	 * <p>
	 * Fires a {@link com.studerb.events.HeaderEvent HeaderEvent} of type
	 * {@link com.studerb.events.HeaderEvent.EventType.ARTICLE_DOWNLOADED
	 * ARTICLE_DOWNLOADED}
	 * 
	 * @param newsGroup
	 * @param taskListeners
	 * @throws ServiceException
	 *             on errors relating to task submission
	 * @see com.studerb.service.interfaces.ITaskService
	 * @see com.studerb.tasks.interfaces.ITaskListener
	 */
	void downloadBody(Post post, ITaskListener... taskListeners) throws ServiceException;

	/**
	 * Creates and submits a task to download all of specific range of post
	 * headers.
	 * <p>
	 * Fires a {@link com.studerb.events.NewsGroupEvent NewsGroupEvent} of type
	 * {@link com.studerb.events.NewsGroupEvent.EventType.HEADERS HEADERS}
	 * indicating that that multiple headers have been updated/created/deleted
	 * 
	 * @param newsGroup
	 * @param first
	 *            article in series to download ({code articleNumber})
	 * @param last
	 *            article in series to download ({code articleNumber})
	 * @param taskListeners
	 * @throws ServiceException
	 *             if task is successfully not started
	 * @see com.studerb.tasks.headers.XoverAllCommandTask
	 * @see com.studerb.service.interfaces.ITaskService
	 * @see com.studerb.tasks.interfaces.ITaskListener
	 */
	void downloadHeaders(NewsGroup newsGroup, int first, int last, ITaskListener... taskListeners) throws ServiceException;

	/**
	 * Creates and submits a task to download all of a headers new articles
	 * since last updated.
	 * <p>
	 * Fires a {@link com.studerb.events.NewsGroupEvent NewsGroupEvent} of type
	 * {@link com.studerb.events.NewsGroupEvent.EventType.HEADERS HEADERS}
	 * indicating that that multiple headers have been updated/created/deleted
	 * 
	 * @param newsGroup
	 * @param taskListeners
	 * @throws ServiceException
	 *             on errors relating to task submission
	 * @see com.studerb.tasks.headers.XoverAllCommandTask
	 * @see com.studerb.service.interfaces.ITaskService
	 * @see com.studerb.tasks.interfaces.ITaskListener
	 */
	void downloadNewHeaders(NewsGroup newsGroup, ITaskListener... taskListeners) throws ServiceException;

	/**
	 * Returns ALL the newsgroups posts. Implementations can use caching to
	 * avoid going to the database for headers everytime, since some newsgroups
	 * list of headers may be extremely large. Implementations should return the
	 * list sorted by article number
	 * 
	 * @param newsGroup
	 *            of the headers to obtain
	 * @param min
	 *            minimum article number of headers to obtain (inclusive) - if
	 *            min is null then minimum article in the persistence is
	 *            implicitly set as the mininum
	 * @param max
	 *            maximum article number of headers to obtain (inclusive) - if
	 *            max is null then maximum article in the persistence is
	 *            implicitly set as the maximum
	 * @return List of Headers between (inclusive) the min and max article
	 *         number
	 */
	// List<Header> getPosts(NewsGroup newsGroup, Long min, Long max);
	/**
	 * Return a list (sorted by current article part) of persisted headers
	 * belonging to a specific {@link com.studerb.model.HeaderThread
	 * HeaderThread}
	 * 
	 * @param HeaderThread
	 * @return List of headers for a given thread sorted by part number
	 */
	List<Header> getHeadersByThread(HeaderThread headerThread);

	/**
	 * Obtain all the {@link com.studerb.model.Post Posts} for a particular
	 * group
	 * 
	 * @param newsGroup
	 * @return list of Posts
	 */
	// List<Post> getPosts(NewsGroup newsGroup);
	/**
	 * Obtain the {@link com.studerb.model.Post Posts} for a particular group
	 * with article numbers between (inclusive) the given parameters.
	 * 
	 * @param newsGroup
	 * @param min
	 *            minimum article number to download (inclusive); if null,
	 *            smallest article number persisted is implicitly set to min
	 * @param max
	 *            maximum article number to download (inclusive); if null,
	 *            largest article number persisted is implicitly set to max
	 * @param max
	 * @return list of Posts
	 */
	List<Post> getPosts(NewsGroup newsGroup, Long min, Long max);

	/**
	 * Obtains a non-singleton runnable object that is passed a queue from which
	 * the {@link com.studerb.tasks.XoverAllCommandTask XoverAllCommandTask} and
	 * {@link com.studerb.tasks.XoverNewCommandTask XoverNewCommandTask} can
	 * efficiently save/modify/delete headers obtained via the 'xover' nntp
	 * command
	 * <p>
	 * This could just be a method in the interface, but in order to speed
	 * things up we use a separate object that can keep state and avoid multiple
	 * transactions / database sessions
	 * 
	 * @param queue
	 *            that the Xover Task passes lines of text representing headers
	 *            for a specific newsgroup
	 * @param Newsgroup
	 *            for which the xover command is called on
	 * @return callable object that the task can use to process.
	 */
	Callable<Void> getXoverCommandProcessor(BlockingQueue<String> queue, NewsGroup newsGroup);

	/**
	 * Parses a standard multi-part nntp header subject into its 'threaded
	 * subject' which includes the subject and its min and max part numbers
	 * 
	 * @param header
	 * @return ParsedSubject object bean containing the modified subject, min,
	 *         and max part numbers
	 */
	// public ParsedSubject parseSubject(Header header);
	/**
	 * Saves a list of new headers for a specific newsgroup The list of headers
	 * are required to be sent in order of article number (ascending). Failure
	 * to do this will result in erronous data being deleted
	 * 
	 * @param list
	 *            of new headers created that should be saved into persistence
	 *            and also the
	 *            <p>
	 *            Because this method is expected for bulk operations (nntp
	 *            'xover' command) individual events are not fired for each save
	 *            / update. Instead a generic
	 *            {@link com.studerb.events.NewsGroupEvent.HEADERS HEADERS
	 *            event} is sent indicating large update of one newsgroups
	 *            headers has occurred.
	 *            <p>
	 * @param newsGroup
	 */
	void saveHeaders(List<Header> headers, NewsGroup newsGroup);

	/**
	 * updates a post to have it's attribute {@code articleDownloaded} to true
	 * <p>
	 * Fires {@link com.studerb.events.HeaderEvent HeaderEvent} of type
	 * {@link com.studerb.events.HeaderEvent.EventType.UPDATED UPDATED}.
	 * 
	 * @param Post
	 *            to update
	 */
	void setArticleDownloaded(Post post);
}
